package com.sztz.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * AES加解密工具类
 * @author yzy
 * @date 2022/7/28 14:09
 */
public class AesUtils {
    /**
     * 密钥，256位32个字节
     */
    private static final byte[] SECRET_KEY="Ubc14DSe&#ad$#ae57feD#E145eRf36o".getBytes(StandardCharsets.UTF_8);
    /**
     * 密钥长度，128位16个字节，192位24个字节，256位32个字节
     */
    private static final int[] AES_KEY_SIZE = new int[]{16, 24, 32};
    /**
     * 初始化向量，128位16个字节
     */
    private static final byte[] KEY_IV = "P8aF*15Ae&aE1FA^".getBytes(StandardCharsets.UTF_8);
    /**
     * Base64解码
     */
    private static java.util.Base64.Decoder base64Decoder = java.util.Base64.getDecoder();

    private AesUtils(){
        throw new IllegalStateException("该类不允许使用构造方法");
    }

    /**
     * 对数据进行AES加密,需要传入密钥
     * @param key 密钥，支持三种密钥长度：128、192、256位,默认256位的SECRET_KEY
     * @param context 需要加密的数据
     * @return String 加密后的数据
     * @author yzy
     * @date 2022/07/28 14:20
     */
    public static String encodeByKey(String key, String context){
        checkKey(key);
        return encode(key.getBytes(StandardCharsets.UTF_8),context);
    }

    /**
     * 对数据进行AES256加密，默认256位的SECRET_KEY密钥
     * @param context 需要加密的数据
     * @return String 加密后的数据
     * @author yzy
     * @date 2022/07/28 14:20
     */
    public static String encode256( String context){
        return encode(SECRET_KEY,context);
    }
    /**
     * 对数据进行AES256加密
     * @param secretKey 密钥字节数组
     * @param context 需要加密的数据字节数组
     * @return String 加密后的数据
     * @author yzy
     * @date 2022/07/28 14:20
     */
    private static String encode(byte[] secretKey, String context){
        return initAes(secretKey).encryptBase64(context);
    }
    /**
     * 对数据进行AES解密,传入密钥
     * @param key 字符串密钥，支持三种密钥长度：128、192、256位，默认256位的SECRET_KEY
     * @param context 需要加密的字符串数据
     * @return String 解密后的数据
     * @author yzy
     * @date 2022/07/28 14:39
     */
    public static String decodeByKey(String key, String context){
        checkKey(key);
        return decode(key.getBytes(StandardCharsets.UTF_8),base64Decoder.decode(context));
    }
    /**
     * 对数据进行AES256解密，使用默认256位的密钥
     * @param context 需要加密的字符串数据
     * @return String 解密后的数据
     * @author yzy
     * @date 2022/07/28 14:39
     */
    public static String decode256(String context){
        return decode(SECRET_KEY,base64Decoder.decode(context));
    }
    /**
     * 对数据进行AES256解密
     * @param secretKey 密钥字节数组
     * @param context 需要加密的数据字节数组
     * @return String 解密后的数据
     * @author yzy
     * @date 2022/07/28 14:39
     */
    private static String decode(byte[] secretKey, byte[] context){
        return initAes(secretKey).decryptStr(context);
    }
    /**
     * 初始化AES算法实现
     * @param secretKey 密钥，支持三种密钥长度：128、192、256位
     * @return AES 算法实现
     * @author yzy
     * @date 2022/07/28 14:39
     */
    private static AES initAes(byte[] secretKey) {
        AES aes = new AES(Mode.CBC, Padding.PKCS5Padding,secretKey);
        aes.setIv(KEY_IV);
        return aes;
    }

    /**
     * 校验密钥
     * @param key 密钥，支持三种密钥字节长度：16、24、32
     * @author yzy
     * @date 2022/07/28 15:53
     */
    private static void checkKey(String key) {
        if(StrUtil.isBlank(key)){
            throw new IllegalArgumentException("密钥不能为空");
        }
        if(Arrays.stream(AES_KEY_SIZE).noneMatch(item -> item == key.length())){
            throw new IllegalArgumentException("密钥长度无效，只能是16字节，24字节或32字节");
        }
    }
}
